/*
 * Copyright 2009 Eat Local Food, LLC
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.common.client.model;

import java.util.Date;

import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;



/**
 * Class that acts as a client to a JSON service. 
 */

public abstract class AbstractModel
{

	public static DateTimeFormat dateTimeFormat =  DateTimeFormat.getFormat("yyyy-MM-dd HH:mm:ss");
	
	public AbstractModel()
	{
	}

	public static String convertToString(JSONObject jsonObject, String label)
	{
		return convertToString(jsonObject, label, "");
	}

	public static int convertToInteger(JSONObject jsonObject, String label)
	{
		return convertToInteger(jsonObject, label, 0);
	}

	public static double convertToDouble(JSONObject jsonObject, String label)
	{
		return convertToDouble(jsonObject, label, 0.0);
	}

	public static boolean convertToBoolean(JSONObject jsonObject, String label)
	{
		return convertToBoolean(jsonObject, label, false);
	}

	public static Date convertToDate(JSONObject jsonObject, String label)
	{
		return convertToDate(jsonObject, label, null);
	}
	
	public static String convertToString(JSONObject jsonObject, String label, String defaultValue)
	{
		if (jsonObject == null) return defaultValue;
		JSONValue jsonValue = jsonObject.get(label);
		if (jsonValue == null) return defaultValue;
		JSONString jsonString = jsonValue.isString();
		if (jsonString == null) return defaultValue;
		return jsonString.stringValue();
		
	}

	public static int convertToInteger(JSONObject jsonObject, String label, int defaultValue)
	{
		if (jsonObject == null) return defaultValue;
		JSONValue jsonValue = jsonObject.get(label);
		if (jsonValue == null) return defaultValue;
		JSONNumber jsonNumber = jsonValue.isNumber();
		if (jsonNumber == null) return defaultValue;
		return (int)jsonNumber.doubleValue();
	}

	public static double convertToDouble(JSONObject jsonObject, String label, double defaultValue)
	{
		if (jsonObject == null) return defaultValue;
		JSONValue jsonValue = jsonObject.get(label);
		if (jsonValue == null) return defaultValue;
		JSONNumber jsonNumber = jsonValue.isNumber();
		if (jsonNumber == null) return defaultValue;
		return jsonNumber.doubleValue();
	}

	public static boolean convertToBoolean(JSONObject jsonObject, String label, boolean defaultValue)
	{
		if (jsonObject == null) return defaultValue;
		JSONValue jsonValue = jsonObject.get(label);
		if (jsonValue == null) return defaultValue;
		JSONBoolean jsonBoolean = jsonValue.isBoolean();
		if (jsonBoolean == null) return defaultValue;
		return jsonBoolean.booleanValue();
	}

	public static Date convertToDate(JSONObject jsonObject, String label, Date defaultValue)
	{
		if (jsonObject == null) return defaultValue;
		JSONValue jsonValue = jsonObject.get(label);
		if (jsonValue == null) return defaultValue;
		JSONString jsonString = jsonValue.isString();
		if (jsonString == null) return defaultValue;
		
		Date value = null;
		try {
			value = dateTimeFormat.parse(jsonString.stringValue());
		}
		catch (Exception e) {value = defaultValue;}
		return value;
	}


	/**
	 * Returns a string array where first location is adjusted with and second location is adjusted height.  The new width and
	 * height will fit inside the box defined by the max width and height.
	 * @param imageWidth
	 * @param imageHeight
	 * @param imageWidthMax
	 * @param imageHeightMax
	 * @return width and height in a string array.
	 */
	public static String[] adjustedImageSize(double imageWidth, double imageHeight, double imageWidthMax, double imageHeightMax)
	{
		long width = Math.round(imageWidth);
		long height = Math.round(imageHeight);

		String[] returnArray = new String[2];
		returnArray[0] = String.valueOf(width);
		returnArray[1] = String.valueOf(height);

		double heightRatio = -1;
		double widthRatio = -1;

		heightRatio = imageHeightMax / imageHeight;
		long hWidth  = Math.round(heightRatio * width);
		long hHeight = Math.round(heightRatio * height);
		if (hWidth < imageWidthMax +1) 
		{
			returnArray[0] = String.valueOf(hWidth);
			returnArray[1] = String.valueOf(hHeight);				
		}
		else
		{
			widthRatio = imageWidthMax / width;
			long wHeight = Math.round(widthRatio * height);
			long wWidth  = Math.round(widthRatio * width);
			if (wHeight < imageHeightMax + 1) 
			{
				returnArray[0] = String.valueOf(wWidth);
				returnArray[1] = String.valueOf(wHeight);				
			}
		}

		return returnArray;
	}
	
	/**
	 * Return a qty that is forced to be a multiple of qtyBlocks.
	 * @param qty
	 * @param qtyBlocks
	 * @return
	 */
	public static int adjustedQuantity(int qty, int qtyBlocks)
	{
		if (qty < 1) qty = 1;

		int adjustedQty = qty;

		if (qtyBlocks > 1)
		{
			if (qty < qtyBlocks)
				adjustedQty = qtyBlocks;
			else if (qty % qtyBlocks != 0)
				adjustedQty  = qty + (qtyBlocks - (qty % qtyBlocks));
		}

		return adjustedQty;
	}
}
